﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SPMS.Utility;
using System.Globalization;

namespace SPMS.Log.ObjectFormatter
{
    /// <summary>
    /// 默认的对象格式化器
    /// </summary>
    /// <remarks>提供了对象格式化器的默认实现</remarks>
    /// <history>
    /// [zanezeng]               2009/9/29 11:51    创建
    /// </history>
    public sealed class DefaultObjectFormatter : AbstractObjectFormatter
    {
        #region ---Constructor

        /// <summary>
        /// 初始化类型<see cref="DefaultObjectFormatter"/>的新实例
        /// </summary>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/29 11:53    创建
        /// </history>
        private DefaultObjectFormatter()
        {
        }

        #endregion

        #region ---Protected Method

        /// <summary>
        /// 将指定的对象格式化为字符串
        /// </summary>
        /// <param name="provider">对象格式化器提供者</param>
        /// <param name="obj">要格式化的对象</param>
        /// <param name="format">对象的格式化字符串</param>
        /// <param name="formatProvider">格式化提供者，提供用于检索控制格式化的对象的机制</param>
        /// <returns>给定对象的字符串描述信息</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 13:19    创建
        /// </history>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 15:30    创建
        /// </history>
        protected override string FormatObject( IObjectFormatterProvider provider, object obj, string format, IFormatProvider formatProvider )
        {
            //判断对象是否为空引用
            if (null == obj)
            {
                //返回格式化的空引用对象
                return FORMATED_NULL_OBJECT;
            }

            //判断是否设置了对象格式化提供者
            if (null == formatProvider)
            {
                //如果没有设置，则默认为区域无关文化设定
                formatProvider = CultureInfo.InvariantCulture;
            }

            //判断是否为数组
            if (obj is Array)
            {
                //格式化数组
                return FormatArray( provider, (Array)obj, format, formatProvider );
            }
            //判断是否为字典条目
            else if (obj is System.Collections.DictionaryEntry)
            {
                //格式化字典条目
                return FormatDictionaryEntry( provider, (System.Collections.DictionaryEntry)obj, format, formatProvider );
            }
            //判断是否为集合
            else if (obj is System.Collections.ICollection)
            {
                //格式化集合
                return FormatCollection( provider, (System.Collections.ICollection)obj, format, formatProvider );
            }

            //用于保存格式化的对象
            string formattedObject = null;

            //转化为可格式化对象
            IFormattable formattable = obj as IFormattable;

            //判断是否为可格式化对象
            if (null != formattable)
            {
                //如果是可格式化对象，则调用对象的格式化操作
                formattedObject = formattable.ToString( format, formatProvider );
            }
            else
            {
                //直接转换为字符串
                formattedObject = obj.ToString();
            }

            //返回字符串描述
            return (null == formattedObject) ? FORMATED_NULL_OBJECT : formattedObject;
        }

        #endregion

        /// <summary>
        /// 格式化给定的数组
        /// </summary>
        /// <param name="provider">对象格式化器提供者</param>
        /// <param name="array">要格式化的数组对象</param>
        /// <param name="format">对象的格式化字符串</param>
        /// <param name="formatProvider">格式化提供者，提供用于检索控制格式化的对象的机制</param>
        /// <returns>给定数组对象的字符串描述信息</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 14:48    创建
        /// </history>
        private static string FormatArray( IObjectFormatterProvider provider, Array array, string format, IFormatProvider formatProvider )
        {
            //创建字符串构建器
            StringBuilder builder = new StringBuilder();

            //用于保存格式化的对象
            string formattedObject = null;

            //判断是否为一维数组
            if (array.Rank == 1)
            {
                //添加数组类型
                builder.Append( array.GetType().Name );

                //添加数组开始标识
                builder.Append( LEFT_QUALIFIER );

                //判断数组的长度是否大于0
                if (array.Length > 0)
                {
                    //格式化对象
                    formattedObject = provider.FormatObject( array.GetValue( 0 ), format, formatProvider );

                    //写入第一个元素
                    builder.Append( formattedObject );
                }

                //循环写入数组的元素
                for (int index = 1; index < array.Length; index++)
                {
                    //写入数组元素的分隔符
                    builder.Append( SEPERATOR_ELEMENT );

                    //格式化对象
                    formattedObject = provider.FormatObject( array.GetValue( index ), format, formatProvider );

                    //写入第一个元素
                    builder.Append( formattedObject );
                }

                //添加数组结束标识
                builder.Append( RIGHT_QUALIFIER );
            }
            //判断是否为二维数组
            else if (array.Rank == 2)
            {
                //添加数组类型
                builder.Append( array.GetType().Name );

                //添加数组开始标识
                builder.Append( LEFT_QUALIFIER );

                //判断数组的长度是否大于0
                if (array.GetLength( 0 ) > 0)
                {
                    //循环写入数组的元素
                    for (int index0 = 0; index0 < array.GetLength( 0 ); index0++)
                    {
                        //添加数组开始标识
                        builder.Append( LEFT_QUALIFIER );

                        //判断数组的长度是否大于0
                        if (array.GetLength( 1 ) > 0)
                        {
                            //格式化对象
                            formattedObject = provider.FormatObject( array.GetValue( 0 ), format, formatProvider );

                            //写入第一个元素
                            builder.Append( formattedObject );
                        }

                        //循环写入数组的元素
                        for (int index1 = 1; index1 < array.GetLength( 0 ); index1++)
                        {
                            //写入数组元素的分隔符
                            builder.Append( SEPERATOR_ELEMENT );

                            //格式化对象
                            formattedObject = provider.FormatObject( array.GetValue( index0, index1 ), format, formatProvider );

                            //写入第一个元素
                            builder.Append( formattedObject );
                        }

                        //添加数组开始标识
                        builder.Append( LEFT_QUALIFIER );
                    }
                }
                else
                {
                    //添加数组开始标识
                    builder.Append( LEFT_QUALIFIER );

                    //添加数组结束标识
                    builder.Append( RIGHT_QUALIFIER );
                }

                //添加数组结束标识
                builder.Append( RIGHT_QUALIFIER );
            }
            else
            {
                //调用系统格式化实现
                builder.Append( array.ToString() );
            }

            //返回格式化的结果
            return builder.ToString();
        }

        /// <summary>
        /// 格式化给定的字典条目
        /// </summary>
        /// <param name="provider">对象格式化器提供者</param>
        /// <param name="entry">要格式化的字典条目</param>
        /// <param name="format">对象的格式化字符串</param>
        /// <param name="formatProvider">格式化提供者，提供用于检索控制格式化的对象的机制</param>
        /// <returns>给定字典条目的字符串描述信息</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 14:48    创建
        /// </history>
        private static string FormatDictionaryEntry( IObjectFormatterProvider provider, System.Collections.DictionaryEntry entry, string format, IFormatProvider formatProvider )
        {
            //创建字符串构建器
            StringBuilder builder = new StringBuilder();

            //添加字典条目的键
            builder.Append( provider.FormatObject( entry.Key ) );

            //添加等号
            builder.Append( SEPERATOR_DICTIONARYENTRY );

            //添加字典条目的值
            builder.Append( provider.FormatObject( entry.Value ) );

            //返回结果
            return builder.ToString();
        }

        /// <summary>
        /// 格式化给定的集合对象
        /// </summary>
        /// <param name="provider">对象格式化器提供者</param>
        /// <param name="collection">要格式化的集合对象</param>
        /// <param name="format">对象的格式化字符串</param>
        /// <param name="formatProvider">格式化提供者，提供用于检索控制格式化的对象的机制</param>
        /// <returns>给定集合对象的字符串描述信息</returns>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2010/1/13 14:48    创建
        /// </history>
        private static string FormatCollection( IObjectFormatterProvider provider, System.Collections.ICollection collection, string format, IFormatProvider formatProvider )
        {
            //创建字符串构建器
            StringBuilder builder = new StringBuilder();

            //用于保存格式化的对象
            string formattedObject = null;

            //添加数组开始标识
            builder.Append( LEFT_QUALIFIER );

            //判断集合是否不为空
            if (collection.Count > 0)
            {
                //获得枚举器
                System.Collections.IEnumerator enumerator = collection.GetEnumerator();

                //判断是否存在元素
                if (null != enumerator && enumerator.MoveNext())
                {
                    //格式化对象
                    formattedObject = provider.FormatObject( enumerator.Current, format, formatProvider );

                    //添加第一个元素
                    builder.Append( formattedObject );

                    //循环添加
                    while (enumerator.MoveNext())
                    {
                        //写入集合的分隔符
                        builder.Append( SEPERATOR_ELEMENT );

                        //格式化对象
                        formattedObject = provider.FormatObject( enumerator.Current, format, formatProvider );

                        //添加第一个元素
                        builder.Append( formattedObject );
                    }
                }
            }

            //添加数组结束标识
            builder.Append( RIGHT_QUALIFIER );

            //返回结果
            return builder.ToString();
        }

        #region ---Property

        /// <summary>
        /// 获得默认实例
        /// </summary>
        /// <value>默认实例</value>
        /// <remarks></remarks>
        /// <history>
        /// [zanezeng]               2009/9/29 11:54    创建
        /// </history>
        public static DefaultObjectFormatter Default
        {
            get
            {
                return DEFAULT_INSTANCE;
            }
        }

        #endregion

        #region ---Field

        /// <summary>
        /// 默认实例
        /// </summary>
        private readonly static DefaultObjectFormatter DEFAULT_INSTANCE = new DefaultObjectFormatter();

        /// <summary>
        /// 元素分隔符
        /// </summary>
        private const string SEPERATOR_ELEMENT = ",";

        /// <summary>
        /// 字典条目之间的分隔符
        /// </summary>
        private const string SEPERATOR_DICTIONARYENTRY = "=";

        /// <summary>
        /// 左侧的限定符
        /// </summary>
        private const string LEFT_QUALIFIER = "{";

        /// <summary>
        /// 右侧的限定符
        /// </summary>
        private const string RIGHT_QUALIFIER = "}";

        /// <summary>
        /// 格式化的空引用对象
        /// </summary>
        private const string FORMATED_NULL_OBJECT = "(null)";

        #endregion
    }
}
